package com.hl.yyx.dto;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hl.yyx.common.constants.MatchMode;

import java.util.Collection;

public class QueryBuilder {
    public static <T> QueryWrapper<T> build(SearchFilters<?> searchFilters) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();

        if (searchFilters == null) {
            return queryWrapper;
        }

        // 构建查询条件
        searchFilters.getFilters().forEach((field, filterItem) -> {
            // 转化驼峰字段名为下划线格式
            String fileName = StringUtils.camelToUnderline(field);
            buildCondition(queryWrapper, fileName, filterItem);
        });

        // 构建排序条件
        if (CollectionUtils.isNotEmpty(searchFilters.getSorts())) {
            for (SortCondition sort : searchFilters.getSorts()) {
                String fieldName = StringUtils.camelToUnderline(sort.getField());
                if (sort.getDirection() == SortCondition.SortDirection.ASC) {
                    queryWrapper.orderByAsc(fieldName);
                } else {
                    queryWrapper.orderByDesc(fieldName);
                }
            }
        }

        return queryWrapper;
    }

    private static <T> void buildCondition(QueryWrapper<T> queryWrapper, String field, FilterItem filterItem) {
        if (field == null || filterItem.getMatchMode() == null) {
            return;
        }

        Object value = filterItem.getValue();
        MatchMode matchMode = filterItem.getMatchMode();
        String relation = StringUtils.isNotBlank(filterItem.getRelation()) ?
                         filterItem.getRelation().toUpperCase() : "AND";

        switch (matchMode) {
            case LIKE:
                applyCondition(queryWrapper, relation, () -> queryWrapper.like(field, value));
                break;
            case EQUAL:
                applyCondition(queryWrapper, relation, () -> queryWrapper.eq(field, value));
                break;
            case NOT_EQUAL:
                applyCondition(queryWrapper, relation, () -> queryWrapper.ne(field, value));
                break;
            case GREATER_THAN:
                applyCondition(queryWrapper, relation, () -> queryWrapper.gt(field, value));
                break;
            case GREATER_THAN_OR_EQUAL:
                applyCondition(queryWrapper, relation, () -> queryWrapper.ge(field, value));
                break;
            case LESS_THAN:
                applyCondition(queryWrapper, relation, () -> queryWrapper.lt(field, value));
                break;
            case LESS_THAN_OR_EQUAL:
                applyCondition(queryWrapper, relation, () -> queryWrapper.le(field, value));
                break;
            case IN:
                if (value instanceof Collection) {
                    applyCondition(queryWrapper, relation, () -> queryWrapper.in(field, (Collection<?>) value));
                } else if (value instanceof Object[]) {
                    applyCondition(queryWrapper, relation, () -> queryWrapper.in(field, (Object[]) value));
                } else if (value != null) {
                    applyCondition(queryWrapper, relation, () -> queryWrapper.in(field, value.toString().split(",")));
                }
                break;
            case BETWEEN:
                if (value instanceof Object[] && ((Object[]) value).length == 2) {
                    Object[] range = (Object[]) value;
                    applyCondition(queryWrapper, relation, () -> queryWrapper.between(field, range[0], range[1]));
                } else if (value instanceof String) {
                    String[] range = ((String) value).split(",");
                    if (range.length == 2) {
                        applyCondition(queryWrapper, relation, () -> queryWrapper.between(field, range[0], range[1]));
                    }
                }
                break;
            case IS_NULL:
                applyCondition(queryWrapper, relation, () -> queryWrapper.isNull(field));
                break;
            case IS_NOT_NULL:
                applyCondition(queryWrapper, relation, () -> queryWrapper.isNotNull(field));
                break;
            default:
                applyCondition(queryWrapper,relation, () -> queryWrapper.eq(field, value));
        }
    }

    private static <T> void applyCondition(QueryWrapper<T> queryWrapper, String relation, Runnable conditionApplier) {
        if ("OR".equals(relation)) {
            // 使用OR连接条件
            queryWrapper.or(wrapper -> conditionApplier.run());
        } else {
            // 默认使用AND连接
            conditionApplier.run();
        }
    }
}